<template>
  <div class="node-editor" @contextmenu.prevent="showContextMenu" @wheel="handleWheel" @mousemove="handleMouseMove"
    @mouseup="handleMouseUp" @mousedown="handleMouseDown" :style="{ cursor: isSpaceDown ? 'grab' : 'default' }">
    <!-- 保存按钮 -->
    <div class="save-button-container">
      <div class="save-button" @click="handleSave">保存</div>
    </div>

    <!-- 缩放控制组 -->
    <div class="zoom-control-container">
      <div class="zoom-button" @click="handleResetZoom">原始大小</div>
      <div class="zoom-button" @click="handleZoomIn">放大</div>
      <div class="zoom-display">{{ Math.round(scale * 100) }}%</div>
      <div class="zoom-button" @click="handleZoomOut">缩小</div>
    </div>

    <!-- 节点编辑器容器 -->
    <div v-if="contextMenu.visible" class="context-menu"
      :style="{ left: `${contextMenu.x}px`, top: `${contextMenu.y}px` }">
      <div class="menu-item" @click="createNode('procedure')">新建节点</div>
    </div>

    <!-- 画布容器，应用缩放变换 -->
    <div class="canvas-container" :style="canvasStyle">
      <!-- 连接线渲染 -->
      <Connection v-for="connection in connections" :key="connection.id" :connection="connection"
        :sourceNode="findNodeById(connection.source)" :targetNode="findNodeById(connection.target)"
        @select="handleConnectionSelect" />

      <!-- 节点渲染 -->
      <Node v-for="node in nodes" :key="node.id" :node="node" :is-selected="selectedNode && selectedNode.id === node.id"
        @select="handleNodeSelect" @update:position="updateNodePosition" @connection-created="handleConnectionCreated"
        @connection-drag-start="handleConnectionDragStart" @connection-drag-end="handleConnectionDragEnd" />
    </div>

    <!-- 连线预览组件 - 放在最外层确保最高层级 -->
    <ConnectionPreview :visible="isDraggingConnection" :startX="connectionStartX" :startY="connectionStartY"
      :endX="connectionEndX" :endY="connectionEndY" />
      
    <!-- 操作指南组件 -->
    <NodeEditorHelp />
  </div>
</template>

<script>
import Node from './Node.vue';
import Connection from './Connection.vue';
import ConnectionPreview from './ConnectionPreview.vue';
import NodeEditorHelp from './NodeEditorHelp.vue';

export default {
  name: 'NodeEditor',
  components: {
    Node,
    Connection,
    ConnectionPreview,
    NodeEditorHelp
  },
  provide() {
    return {
      scale: () => this.scale,
      translateX: () => this.translateX,
      translateY: () => this.translateY
    };
  },
  data() {
    return {
      nodes: [],
      connections: [],
      contextMenu: {
        visible: false,
        x: 0,
        y: 0
      },
      draggingNode: null,
      dragOffsetX: 0,
      dragOffsetY: 0,
      selectedNode: null,
      selectedConnection: null,
      draggingSourceNode: null,
      draggingSourcePortIndex: -1,
      isDraggingConnection: false,
      connectionStartX: 0,
      connectionStartY: 0,
      connectionEndX: 0,
      connectionEndY: 0,
      // 缩放和平移相关变量
      scale: 1,
      translateX: 0,
      translateY: 0,
      // 空格键+左键拖动相关变量
      isSpaceDown: false,
      isLeftMouseDown: false,
      dragStartX: 0,
      dragStartY: 0,
      isDragging: false
    }
  },
  mounted() {
    document.addEventListener('click', this.handleGlobalClick);
    document.addEventListener('keydown', this.handleKeyDown);
    document.addEventListener('keyup', this.handleKeyUp);
  },
  beforeDestroy() {
    document.removeEventListener('click', this.handleGlobalClick);
    document.removeEventListener('keydown', this.handleKeyDown);
    document.removeEventListener('keyup', this.handleKeyUp);
  },
  computed: {
    // 计算画布容器的样式，应用缩放和平移变换
    canvasStyle() {
      return {
        transform: `translate(${this.translateX}px, ${this.translateY}px) scale(${this.scale})`,
        transformOrigin: '0 0'
      };
    }
  },
  methods: {
    handleNodeSelect(node) {
      this.selectedNode = node;
      this.selectedConnection = null;
    },

    handleConnectionSelect(connection) {
      // 先将之前选中的连接线的selected状态设为false
      if (this.selectedConnection) {
        this.selectedConnection.selected = false;
      }
      // 设置新选中的连接线
      this.selectedConnection = connection;
      if (connection) {
        connection.selected = true;
      }
      this.selectedNode = null;
    },

    findNodeById(nodeId) {
      return this.nodes.find(node => node.id === nodeId);
    },

    showContextMenu(e) {
      e.stopPropagation();
      this.contextMenu = {
        visible: true,
        x: e.clientX,
        y: e.clientY
      };
    },

    hideContextMenu() {
      this.contextMenu.visible = false;
    },

    handleGlobalClick(e) {
      const contextMenuEl = document.querySelector('.context-menu');
      if (contextMenuEl && !contextMenuEl.contains(e.target)) {
        this.hideContextMenu();
      }

      // 如果点击空白处，取消节点和连接线的选中状态
      const nodeEl = e.target.closest('.node');
      const connectionEl = e.target.closest('.line-selected');
      if (!nodeEl) {
        this.selectedNode = null;
      }
      if (!connectionEl) {
        console.log('connectionEl', connectionEl);
        // 将当前选中连接线的selected状态重置为false
        if (this.selectedConnection) {
          this.connections.filter(conn => {
            if (this.selectedConnection && conn.id === this.selectedConnection.id) {
              conn.selected = false;
            }
          })
          this.selectedConnection.selected = false;
          this.selectedConnection = null;
        }

      }

      // 重置拖动状态
      this.isDragging = false;
    },

    handleMouseDown(e) {
      // 如果按住空格键并且是鼠标左键
      if (this.isSpaceDown && e.button === 0) {
        this.isLeftMouseDown = true;
        this.dragStartX = e.clientX;
        this.dragStartY = e.clientY;
        this.isDragging = false;

        // 当拖动开始时，将光标样式改为抓取状态
        document.body.style.cursor = 'grabbing';
        e.preventDefault();
      }
    },

    handleMouseMove(e) {
      // 处理空格+左键拖动
      if (this.isSpaceDown && this.isLeftMouseDown) {
        this.isDragging = true;

        // 计算偏移量并更新画布位置
        const deltaX = e.clientX - this.dragStartX;
        const deltaY = e.clientY - this.dragStartY;

        this.translateX += deltaX;
        this.translateY += deltaY;

        // 更新起始位置为当前位置，以便下次计算偏移量
        this.dragStartX = e.clientX;
        this.dragStartY = e.clientY;
      }

      // 处理连线拖拽
      if (this.isDraggingConnection) {
        // 考虑画布的缩放和平移因素
        const editorRect = this.$el.getBoundingClientRect();

        // 将客户端坐标转换为画布坐标
        this.connectionEndX = (e.clientX - editorRect.left - this.translateX) / this.scale;
        this.connectionEndY = (e.clientY - editorRect.top - this.translateY) / this.scale;
      }
    },

    handleMouseUp(e) {
      // 如果是左键并且正在拖动
      if (e.button === 0 && this.isLeftMouseDown) {
        this.isLeftMouseDown = false;
        this.isDragging = false;
        this.isLeftMouseDown = false;
        this.isDragging = false;

        // 恢复光标样式
        if (this.isSpaceDown) {
          document.body.style.cursor = 'grab';
        } else {
          document.body.style.cursor = 'default';
        }
      }
      // 处理连线拖拽结束
      if (this.isDraggingConnection) {

        // const targetPort = e.target.closest('.node-port');
        // if (targetPort && targetPort.classList.contains('node-input')) {
        //   const targetNode = targetPort.closest('.node');
        //   if (targetNode && targetNode.__vue__) {
        //     const index = Array.from(targetPort.parentElement.children).indexOf(targetPort);
        //     const targetNodeComponent = targetNode.__vue__;

        //     // 使用端点的实际坐标创建连接
        //     this.handleConnectionCreated({
        //       source: this.draggingSourceNode.id,
        //       sourcePortIndex: this.draggingSourcePortIndex,
        //       target: targetNodeComponent.$props.node.id,
        //       targetPortIndex: index
        //     });
        //   }
        // }
        this.handleConnectionDragEnd();
      }
    },

    createNode(type) {
      const config = {
        type: 'procedure',
        title: '过程节点',
        inputs: [{ type: 'exec', name: '输入', x: 0, y: 0 }, { type: 'exec', name: '输入', x: 0, y: 0 }],
        outputs: [{ type: 'exec', name: '输出', x: 0, y: 0 }, { type: 'exec', name: '输出', x: 0, y: 0 }]
      };
      // 将视口坐标转换为画布坐标
      const editorRect = this.$el.getBoundingClientRect();
      const canvasX = (this.contextMenu.x - editorRect.left - this.translateX) / this.scale;
      const canvasY = (this.contextMenu.y - editorRect.top - this.translateY) / this.scale;

      const nodeConfig = {
        ...config,
        x: canvasX,
        y: canvasY
      }

      this.addNode(nodeConfig);
      this.hideContextMenu();
    },

    addNode(node) {
      const newNode = {
        ...node,
        id: Date.now().toString(),
        x: node.x,
        y: node.y,
        width: node.width || 150,  // 默认宽度
        height: node.height || 100  // 默认高度
      };
      this.nodes.push(newNode);

      // 添加调试信息：打印新创建的节点信息
      console.log('节点创建:', {
        id: newNode.id,
        type: newNode.type,
        position: { x: newNode.x, y: newNode.y },
        size: { width: newNode.width, height: newNode.height },
        inputs: newNode.inputs,
        outputs: newNode.outputs
      });
    },

    removeNode(nodeId) {
      this.nodes = this.nodes.filter(node => node.id !== nodeId);
      this.connections = this.connections.filter(
        conn => conn.source !== nodeId && conn.target !== nodeId
      );
    },

    // updateNodePosition(nodeId, position) {
    //   const node = this.nodes.find(n => n.id === nodeId);
    //   if (node) {
    //     node.x = position.x;
    //     node.y = position.y;
    //   }
    // },

    removeConnection(connectionId) {
      this.connections = this.connections.filter(
        conn => conn.id !== connectionId
      );
    },

    validateConnection(connection) {

      const { source, sourcePortIndex, target, targetPortIndex } = connection;
      // 防止自连接
      if (source === target) return false;
      // 获取节点实例
      const sourceNode = this.findNodeById(source);
      const targetNode = this.findNodeById(target);

      // 验证端口类型匹配
      const sourcePort = sourceNode.outputs[sourcePortIndex];
      const targetPort = targetNode.inputs[targetPortIndex];
      const isPortValid = sourcePort?.type === targetPort?.type;

      // 防止重复连接
      const existing = this.connections.find(
        conn => conn.source === source &&
          conn.sourcePortIndex === sourcePortIndex &&
          conn.target === target &&
          conn.targetPortIndex === targetPortIndex
      );

      return isPortValid && !existing;
    },

    handleConnectionCreated({ source, sourcePortIndex, target, targetPortIndex, targetPortPosition }) {
      const connection = {
        source,
        sourcePortIndex,
        target,
        targetPortIndex
      };
      console.log('连接创建:', connection);
      if (this.validateConnection(connection)) {
        // 获取源节点和目标节点
        const sourceNode = this.findNodeById(source);
        const targetNode = this.findNodeById(target);

        // 更新目标节点的输入端点坐标
        if (targetNode && targetNode.inputs[targetPortIndex] && targetPortPosition) {
          targetNode.inputs[targetPortIndex].x = targetPortPosition.x;
          targetNode.inputs[targetPortIndex].y = targetPortPosition.y;
        }

        // 创建连接并添加到连接列表
        this.$set(this.connections, this.connections.length, {
          id: `${source}-${sourcePortIndex}-${target}-${targetPortIndex}`,
          selected: false,
          ...connection
        });
      }
      this.draggingSourceNode = null;
    },

    handleKeyDown(e) {
      // 当按下Delete键时，删除选中的节点或连接线
      if (e.key === 'Delete') {
        if (this.selectedNode) {
          this.removeNode(this.selectedNode.id);
          this.selectedNode = null;
        } else if (this.selectedConnection) {
          this.removeConnection(this.selectedConnection.id);
          this.selectedConnection = null;
        }
      }

      // 当按下空格键时，更改光标样式为手型
      if (e.key === ' ' && !this.isSpaceDown) {
        this.isSpaceDown = true;
        document.body.style.cursor = this.isLeftMouseDown ? 'grabbing' : 'grab';
      }
    },

    handleKeyUp(e) {
      // 当释放空格键时，恢复光标样式
      if (e.key === ' ') {
        this.isSpaceDown = false;
        document.body.style.cursor = 'default';

        // 如果松开空格键但鼠标左键仍然按下，则取消拖动状态
        if (this.isLeftMouseDown) {
          this.isLeftMouseDown = false;
          this.isDragging = false;
        }
      }
    },

    updateNodePosition({ id, position, portPositions }) {
      console.log('updateNodePosition called with:', { id, position, portPositions });
      const node = this.nodes.find(n => n.id === id);
      if (node) {
        node.x = position.x;
        node.y = position.y;

        // 更新节点的输入和输出端点坐标
        if (portPositions) {
          node.inputs.forEach((input, index) => {
            if (portPositions.inputs[index]) {
              input.x = portPositions.inputs[index].x;
              input.y = portPositions.inputs[index].y;
            }
          });

          node.outputs.forEach((output, index) => {
            if (portPositions.outputs[index]) {
              output.x = portPositions.outputs[index].x;
              output.y = portPositions.outputs[index].y;
            }
          });
        }

        // 添加调试信息：打印节点移动信息
        console.log('节点移动:', {
          id: node.id,
          type: node.type,
          position: { x: node.x, y: node.y },
          inputs: node.inputs,
          outputs: node.outputs
        });
      }
    },

    // 处理鼠标滚轮事件，实现缩放功能
    handleWheel(e) {
      e.preventDefault();

      // 获取鼠标在编辑器中的位置
      const rect = e.currentTarget.getBoundingClientRect();
      const mouseX = e.clientX - rect.left;
      const mouseY = e.clientY - rect.top;

      // 计算鼠标相对于当前缩放后画布的位置
      const mouseXInCanvas = (mouseX - this.translateX) / this.scale;
      const mouseYInCanvas = (mouseY - this.translateY) / this.scale;

      // 根据滚轮方向调整缩放比例
      const delta = e.deltaY > 0 ? -0.05 : 0.05;
      const newScale = Math.max(0.1, Math.min(2, this.scale + delta));

      // 计算新的缩放比例下，画布应该移动的位置，以保持鼠标指针位置不变
      const newTranslateX = mouseX - mouseXInCanvas * newScale;
      const newTranslateY = mouseY - mouseYInCanvas * newScale;

      // 更新缩放比例和平移位置
      this.scale = newScale;
      this.translateX = newTranslateX;
      this.translateY = newTranslateY;
    },

    // 处理连线拖拽开始
    handleConnectionDragStart({ sourceNode, sourcePortIndex, startX, startY }) {
      this.isDraggingConnection = true;
      this.draggingSourceNode = sourceNode;
      this.draggingSourcePortIndex = sourcePortIndex;
      this.connectionStartX = startX;
      this.connectionStartY = startY;
      this.connectionEndX = startX;
      this.connectionEndY = startY;

      // 更新源节点对应输出端点的坐标
      const node = this.nodes.find(n => n.id === sourceNode.id);
      if (node && node.outputs[sourcePortIndex]) {
        node.outputs[sourcePortIndex].x = startX;
        node.outputs[sourcePortIndex].y = startY;
      }

      document.addEventListener('mousemove', this.handleMouseMove);
      document.addEventListener('mouseup', this.handleMouseUp);
    },

    // 处理连线拖拽结束
    handleConnectionDragEnd() {
      this.isDraggingConnection = false;
      this.draggingSourceNode = null;
      this.draggingSourcePortIndex = -1;
    },

    // 重置缩放比例为1
    handleResetZoom() {
      this.scale = 1;
    },

    // 放大按钮点击处理
    handleZoomIn() {
      this.scale = Math.min(2, this.scale + 0.1);
    },

    // 缩小按钮点击处理
    handleZoomOut() {
      this.scale = Math.max(0.1, this.scale - 0.1);
    },

    handleSave() {
      const editorState = {
        // 保存画布状态
        canvas: {
          scale: this.scale,
          translateX: this.translateX,
          translateY: this.translateY
        },
        // 保存节点信息
        nodes: this.nodes.map(node => ({
          id: node.id,
          type: node.type,
          title: node.title,
          x: node.x,
          y: node.y,
          width: node.width,
          height: node.height,
          inputs: node.inputs,
          outputs: node.outputs
        })),
        // 保存连线信息
        connections: this.connections.map(conn => {
          const sourceNode = this.findNodeById(conn.source);
          const targetNode = this.findNodeById(conn.target);
          const sourcePort = sourceNode.outputs[conn.sourcePortIndex];
          const targetPort = targetNode.inputs[conn.targetPortIndex];

          return {
            id: conn.id,
            source: conn.source,
            sourcePortIndex: conn.sourcePortIndex,
            sourcePort: {
              type: sourcePort.type,
              name: sourcePort.name,
              x: sourcePort.x,
              y: sourcePort.y
            },
            target: conn.target,
            targetPortIndex: conn.targetPortIndex,
            targetPort: {
              type: targetPort.type,
              name: targetPort.name,
              x: targetPort.x,
              y: targetPort.y
            },
            configValue: conn.configValue
          };
        })
      };

      console.log('节点编辑器状态：', JSON.stringify(editorState, null, 2));
    }
  }
}
</script>

<style>
@import '../assets/styles/NodeEditor.css';
</style>